package com.zmx.common.common.config.feign;

import com.google.common.collect.Sets;
import com.zmx.common.common.invocation.InvocationInfo;
import com.zmx.common.common.invocation.InvocationInfoProxy;
import com.zmx.common.common.utils.JacksonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Set;

/**
 * @Description: 线程上下文拦截器
 * @ClassName: InvocationInfoFilter
 * @Author zhaomxr
 * @Date 2022-01-13 19:26
 */
@Slf4j
public class InvocationInfoFilter implements Filter {
    private static final Set<String> IGNORED_CONTENT_TYPES = Sets.newHashSet("application/pdf");

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (!IGNORED_CONTENT_TYPES.contains(request.getContentType())) {
            writeThreadContext((HttpServletRequest)request);
        }
        chain.doFilter(request, response);
    }

    /**
     * 将调用信息放入线程上下文中。
     */
    @SuppressWarnings("unchecked")
    private void writeThreadContext(HttpServletRequest request) {
        String invocationInfoJson = request.getHeader("INVOCATIONINFO");
        if (StringUtils.isNotBlank(invocationInfoJson)) {
            try {
                invocationInfoJson = URLDecoder.decode(invocationInfoJson, "UTF-8");
                InvocationInfo invocationInfo = JacksonUtil.jsonStringToBean(invocationInfoJson,InvocationInfo.class);
                InvocationInfoProxy.set(invocationInfo);
            } catch (UnsupportedEncodingException uee) {
                log.error("编码格式异常。", uee);
            } catch (Exception e) {
                log.error("将调用信息放入线程上下文中时出现异常。", e);
            }
        } else {
            // 调用信息为空时，清空线程上下文
            InvocationInfoProxy.clear();
        }
    }

    @Override
    public void destroy() {
        InvocationInfoProxy.clear();
    }
}
